package net.jiastudy.biz.user.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.jiastudy.core.utils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import net.jiastudy.biz.user.entity.Role;
import net.jiastudy.biz.user.entity.RolePermission;
import net.jiastudy.biz.user.entity.User;
import net.jiastudy.biz.user.entity.UserRole;
import net.jiastudy.biz.user.mapper.RoleMapper;
import net.jiastudy.biz.user.mapper.RolePermissionMapper;
import net.jiastudy.biz.user.mapper.UserRoleMapper;
import net.jiastudy.biz.user.service.RoleService;
import net.jiastudy.core.base.BaseService;
import net.jiastudy.core.exception.NotFoundException;
import net.jiastudy.core.exception.ServiceException;

@Service
@Transactional(rollbackFor = Exception.class)
public class RoleServiceImpl extends BaseService<RoleMapper, Role> implements RoleService {

	@Autowired
	private RoleMapper roleMapper;
	@Autowired
	private RolePermissionMapper rolePermissionMapper;
	@Autowired
	private UserRoleMapper userRoleMapper;

	@Override
	public Role createRole(Role role) {
		if (null == role.getCode()) {
			role.setCode(this.randomCode());
		}
		if (this.checkCodeExists(role.getCode(), null)) {
			throw new NotFoundException("role.code.exists", "角色code已经存在");
		}
		roleMapper.insert(role);
		List<RolePermission> rolePermissions = role.getRolePermissions();
		if (null != rolePermissions) {
			for (RolePermission rolePermission : rolePermissions) {
				rolePermission.setRole(role);
				rolePermissionMapper.insert(rolePermission);
			}
		}
		return role;
	}

	private String randomCode() {
		String code = "ROLE_" + RandomUtil.randomStringUpper(16);
		while (this.checkCodeExists(code, null)) {
			code = "ROLE_" + RandomUtil.randomStringUpper(16);
		}
		return code;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public Role updateRole(Role role) {
		if (this.checkCodeExists(role.getCode(), role.getId())) {
			throw new NotFoundException("role.code.exists", "角色code已经存在");
		}
		roleMapper.updateById(role);
		Map<String, Object> condition = new HashMap<String, Object>();
		condition.put("role_id", role.getId());
		rolePermissionMapper.deleteByMap(condition);
		List<RolePermission> rolePermissions = role.getRolePermissions();
		if (null != rolePermissions) {
			for (RolePermission rolePermission : rolePermissions) {
				rolePermission.setRole(role);
				rolePermissionMapper.insert(rolePermission);
			}
		}
		return role;
	}

	@Override
	public boolean checkCodeExists(String code, Long roleId) {
		if (null == code) {
			return false;
		}
		Role entity = new Role();
		entity.setCode(code);
		Role role = roleMapper.selectOne(entity);
		if (null == role) {
			return false;
		}
		if (role.getId().equals(roleId)) {
			return false;
		}
		return true;
	}

	@Override
	public boolean addUserRoles(User user, List<Long> roleIds) {
		this.clearUserRoles(user.getId());
		for (Long id : roleIds) {
			Role role = roleMapper.selectById(id);
			if (null == role) {
				throw new ServiceException("role.notExists", id + "ID的角色不存存");
			}
			this.addUserRoles(user.getId(), role.getId());
		}
		return true;
	}

	@Override
	public boolean addUserRoles(Long userId, Long roleId) {
		UserRole ur = new UserRole();
		ur.setUserId(userId);
		ur.setRoleId(roleId);
		if (null != userRoleMapper.selectOne(ur)) {
			return true;
		}
		return retBool(userRoleMapper.insert(ur));
	}

	private boolean clearUserRoles(Long userId) {
		Wrapper<UserRole> wrapper = new EntityWrapper<>();
		wrapper.eq("user_id", userId);
		userRoleMapper.delete(wrapper);
		return true;
	}

	@Override
	public boolean addUserRolesByCode(User user, List<String> roleCodes) {
		this.clearUserRoles(user.getId());
		for (String code : roleCodes) {
			Role entity = new Role();
			entity.setCode(code);
			Role role = roleMapper.selectOne(entity);
			if (null == role) {
				throw new ServiceException("role.notExists", code + "的code角色不存存");
			}
			this.addUserRoles(user.getId(), role.getId());
		}
		return true;
	}

	@Override
	public Set<String> findPermissionsByUserId(Long userId) {
		return userRoleMapper.findPermissionsByUserId(userId);
	}

	@Override
	public Set<String> findRoleCodesByUserId(Long userId) {
		return userRoleMapper.findRoleCodesByUserId(userId);
	}

	@Override
	public boolean deleteRole(Long id) {
		Role role = roleMapper.selectById(id);
		if (null == role) {
			return true;
		}
		if (role.isSysRole()) {
			throw new ServiceException("role.not.delete", "系统角色不可以被删除！");
		}
		EntityWrapper<RolePermission> ew = new EntityWrapper<RolePermission>();
		ew.eq("ROLE_ID", id);
		rolePermissionMapper.delete(ew);
		return retBool(roleMapper.deleteById(id));
	}

	@Override
	public Role getRoleById(Long id) {
		Role role = roleMapper.selectById(id);
		if (null == role) {
			throw new NotFoundException("404", "角色不存在");
		}
		EntityWrapper<RolePermission> ew = new EntityWrapper<RolePermission>();
		ew.eq("ROLE_ID", id);
		role.setRolePermissions(rolePermissionMapper.selectList(ew));
		return role;
	}

	@Override
	public Role getRoleByCode(String code) {
		Role entity = new Role();
		entity.setCode(code);
		Role role = roleMapper.selectOne(entity);

		if (null == role) {
			throw new NotFoundException("404", "角色不存在");
		}
		EntityWrapper<RolePermission> ew = new EntityWrapper<RolePermission>();
		ew.eq("ROLE_ID", role.getId());
		role.setRolePermissions(rolePermissionMapper.selectList(ew));
		return role;
	}

	@Override
	public Page<Role> searchRoles(Page<Role> page, Map<String, String> conditions, Sort sort) {
		Wrapper<Role> wrapper = new EntityWrapper<>();
		this.generateSort(wrapper, sort);
		if (conditions.containsKey("keywords") && StrUtil.isNotEmpty(conditions.get("keywords"))) {
			String keywords = conditions.get("keywords");
			wrapper.andNew().like("name", keywords).or().like("code", keywords);
		}
		return selectPage(page, wrapper);
	}

	@Override
	public Set<Role> findRolesByUserId(Long userId) {
		return userRoleMapper.findRolesByUserId(userId);
	}

	@Override
	public List<Role> findRolesAll(String keywords) {
		EntityWrapper<Role> wrapper = new EntityWrapper<>();
		wrapper.like("name", keywords);
		return roleMapper.selectList(wrapper);
	}

	@Override
	public Set<Long> findRoleUserIdsByRoleId(Long roleId) {
		Wrapper<UserRole> wrapper = new EntityWrapper<>();
		wrapper.eq("role_id", roleId);

		List<UserRole> userRoles = userRoleMapper.selectList(wrapper);
		Set<Long> userIds = BeanUtils.getFiled(userRoles, "userId", long.class);

		return userIds;
	}

	@Override
	public boolean isUserExistRole(Long userId, String roleCode) {
		Set<String> codes = this.findRoleCodesByUserId(userId);
		if (null == codes) {
			return false;
		}
		for (String code : codes) {
			if (code.equals(roleCode)) {
				return true;
			}
		}
		return false;
	}

}
